package com.qijian.tool.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qijian.common.annotation.Anonymous;
import com.qijian.common.annotation.Log;
import com.qijian.common.core.controller.BaseController;
import com.qijian.common.core.domain.AjaxResult;
import com.qijian.common.core.page.TableDataInfo;
import com.qijian.common.core.redis.RedisCache;
import com.qijian.common.enums.BusinessType;
import com.qijian.common.exception.ServiceException;
import com.qijian.common.utils.StringUtils;
import com.qijian.common.utils.file.FileUtils;
import com.qijian.common.utils.mybatis.WhereEntityTool;
import com.qijian.common.utils.poi.ExcelUtil;
import com.qijian.tool.config.FileProperties;
import com.qijian.tool.domain.Storage;
import com.qijian.tool.domain.query.StorageQuery;
import com.qijian.tool.service.IStorageService;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 数据存储Controller
 *
 * @author qijian
 * @date 2021-09-06
 */
@Api(tags = "数据存储")
@RestController
@RequiredArgsConstructor
@RequestMapping("/tools/storage")
public class StorageController extends BaseController {

    private final IStorageService storageService;
    private final FileProperties properties;
    private final RedisCache redisCache;

    private final String prefix = "image:";

    /**
     * 查询数据存储列表
     */
    @GetMapping("/list")
    public TableDataInfo list(StorageQuery query, IPage<Storage> page) {
        return getDataTable(storageService.page(Page.of(page.getCurrent(), page.getSize()), WhereEntityTool.invoke(query)));
    }

    @GetMapping("/getUrl")
    public AjaxResult getUrl(StorageQuery query) {
        String key = String.format("%s%s%s", prefix, query.getClassTable(), query.getClassId());
        String url = redisCache.getCacheObject(key);
        if (StringUtils.isEmpty(url)) {
            List<Storage> storageList = storageService.list(WhereEntityTool.invoke(query));
            if (CollectionUtil.isNotEmpty(storageList)) {
                url = storageList.get(0).getUrl();
                redisCache.setCacheObject(key, url, 1, TimeUnit.DAYS);
            }
        }
        return AjaxResult.success(url);
    }

    @GetMapping("/getUrlList")
    public AjaxResult getUrlList(StorageQuery query) {
        if (query.getClassId() == null) {
            throw new ServiceException("E01:信息不能为空");
        }
        String key = String.format("%s:%s:%s:%s", prefix, StringUtils.isNotEmpty(query.getClassTable()) ? query.getClassTable() : "", query.getClassId(), query.getClassify() == null ? "" : query.getClassify());
        List<Storage> list = redisCache.getCacheList(key);
        if (CollectionUtil.isEmpty(list)) {
            List<Storage> storageList = storageService.list(WhereEntityTool.invoke(query));
            list = new ArrayList<>(storageList.size());
            for (Storage action : storageList) {
                action.setStorageId(null);
                list.add(action);
            }

            if (CollectionUtil.isNotEmpty(list)) {
                redisCache.setCacheList(key, list);
                redisCache.expire(key, 1, TimeUnit.DAYS);
            }
        }
        return AjaxResult.success(list);
    }

    /**
     * 导出数据存储列表
     */
    @PreAuthorize("@ss.hasPermi('tools:storage:export')")
    @Log(title = "数据存储", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(StorageQuery query) {
        return new ExcelUtil<>(Storage.class).exportExcel(storageService.list(WhereEntityTool.invoke(query)), "数据存储数据");
    }

    /**
     * 获取数据存储详细信息
     */
    @PreAuthorize("@ss.hasPermi('tools:storage:query')")
    @GetMapping(value = "/{storageId}")
    public AjaxResult getInfo(@PathVariable("storageId") Long storageId) {
        return AjaxResult.success(storageService.getById(storageId));
    }

    @GetMapping(value = "/getByClassId/{classId}")
    public AjaxResult getByClassId(@PathVariable("classId") String classId) {
        StorageQuery query = new StorageQuery();
        query.setClassIdArray(classId.split(","));
        return AjaxResult.success(storageService.list(WhereEntityTool.invoke(query)));
    }

    /**
     * 新增数据存储
     */
//    @PreAuthorize("@ss.hasPermi('tools:storage:add')")
    @Log(title = "数据存储", businessType = BusinessType.INSERT)
    @PostMapping("withWatermark")
    public AjaxResult withWatermark(@RequestParam(required = false, value = "classTable") String classTable, @RequestParam(required = false, value = "classId") Long classId, @RequestParam(required = false, value = "classify") Integer classify, @RequestParam(required = false, value = "description") String description, @RequestParam("file") MultipartFile file, @RequestParam(required = false, value = "folder") String folder) {
        // 删除缓存
        if (classId != null) {
            redisCache.deleteObject(String.format("%s%s%s", prefix, StringUtils.isNotEmpty(classTable) ? classTable : "", classId));
        }
        String suffix = FileUtils.getExtensionName(file.getOriginalFilename());
        folder = StringUtils.isBlank(folder) ? StringUtils.isBlank(classTable) ? FileUtils.getFolder(suffix) : classTable : folder;
        return AjaxResult.success(storageService.addStoreDataWithWatermark(classTable, classId, classify, description, file, folder, suffix));
    }

    @Anonymous
    @Log(title = "数据存储", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestParam(required = false, value = "classTable") String classTable, @RequestParam(required = false, value = "classId") Long classId, @RequestParam(required = false, value = "classify") Integer classify, @RequestParam(required = false, value = "description") String description, @RequestParam("file") MultipartFile file, @RequestParam(required = false, value = "folder") String folder) {
        // 删除缓存
        if (classId != null) {
            redisCache.deleteObject(String.format("%s%s%s", prefix, StringUtils.isNotEmpty(classTable) ? classTable : "", classId));
        }
        String suffix = FileUtils.getExtensionName(file.getOriginalFilename());
        folder = StringUtils.isBlank(folder) ? StringUtils.isBlank(classTable) ? FileUtils.getFolder(suffix) : classTable : folder;
        return AjaxResult.success(storageService.addStoreData(classTable, classId, classify, description, file, folder, suffix));
    }

    @Log(title = "附件复制", businessType = BusinessType.INSERT)
    @PostMapping(value = "/copy/{ids}")
    public AjaxResult copy(@PathVariable("ids") String ids) {
        StorageQuery query = new StorageQuery();
        String[] idAry = ids.split(",");
        Set<Long> idsSet = new HashSet<>(idAry.length);
        for (String id : idAry) {
            idsSet.add(Long.valueOf(id));
        }
        query.setStorageIds(idsSet);
        List<Storage> storages = storageService.list(WhereEntityTool.invoke(query));
        if (CollectionUtil.isEmpty(storages)) {
            throw new ServiceException("E01:附件错误");
        }
        storages.forEach(storage -> storage.setStorageId(null));
        storageService.saveBatch(storages);
        return AjaxResult.success(storages);
    }

    @Log(title = "流程数据存储", businessType = BusinessType.INSERT)
    @PostMapping(value = "/uploadProcess")
    public AjaxResult uploadProcess(@RequestParam(required = false, value = "description") String description, @RequestParam("file") MultipartFile file) {
        String folder = "flowable";
        return AjaxResult.success(storageService.addStoreData(folder, null, 1, description, file, folder, FileUtils.getExtensionName(file.getOriginalFilename())));
    }


    @Anonymous
    @Log(title = "报价附件存储", businessType = BusinessType.INSERT)
    @PostMapping(value = "/uploadOffer/{uuid}")
    public AjaxResult uploadOffer(@PathVariable("uuid") String uuid, @RequestParam("file") MultipartFile[] files, @RequestParam("classId") Long classId) {
        if (CollectionUtil.isEmpty(redisCache.keys("*".concat(uuid)))) {
            throw new ServiceException("E01:无权限操作");
        }
        return setStoreDataFiles("offer", classId, 2, files, "offer");
    }

    @Anonymous
    @Log(title = "报价附件存储", businessType = BusinessType.INSERT)
    @PostMapping(value = "/uploadOutOffer/{uuid}")
    public AjaxResult uploadOffer(@PathVariable("uuid") String uuid, @RequestParam("file") MultipartFile[] files, @RequestParam("classId") Long classId, @RequestParam("description") String description) {
        if (CollectionUtil.isEmpty(redisCache.keys("*".concat(uuid)))) {
            throw new ServiceException("E01:无权限操作");
        }

        List<Storage> storages = new ArrayList<>();
        for (MultipartFile file : files) {
            Storage storage = storageService.addStoreData("offer", classId, 2, description, file, "offer", FileUtils.getExtensionName(file.getOriginalFilename()));
            storages.add(storage);
        }
        return AjaxResult.data(storages);
    }


    private AjaxResult setStoreDataFiles(String classTable, Long classId, Integer classify, MultipartFile[] files, String folder) {
        List<Storage> storages = new ArrayList<>();
        for (MultipartFile file : files) {
            Storage storage = storageService.addStoreData(classTable, classId, classify, null, file, folder, FileUtils.getExtensionName(file.getOriginalFilename()));
            storages.add(storage);
        }
        return AjaxResult.data(storages);
    }

    /**
     * 修改数据存储
     */
    @PreAuthorize("@ss.hasPermi('tools:storage:edit')")
    @Log(title = "数据存储", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Storage storage) {
        return toAjax(storageService.updateById(storage));
    }

    /**
     * 删除数据存储
     */
//    @PreAuthorize("@ss.hasAnyPermi('tools:storage:remove,business:eqp:list,business:reviewPlan:list')")
    @Log(title = "数据存储", businessType = BusinessType.DELETE)
    @DeleteMapping("/{storageIds}")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult remove(@PathVariable List<Long> storageIds) {
        storageService.removeAndFileByIds(storageIds);
        return AjaxResult.success();
    }

    /**
     * 删除数据存储带模块
     */
//    @PreAuthorize("@ss.hasAnyPermi('tools:storage:remove,business:eqp:list,business:reviewPlan:list')")
    @Log(title = "删除数据存储带模块", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteWithModule/{storageIds}")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult remove(@PathVariable List<Long> storageIds,String module) {
        storageService.removeAndFileWithModule(storageIds,module);
        return AjaxResult.success();
    }


    @PostMapping("cad/unzip")
    public AjaxResult unzip(@RequestParam(value = "file") MultipartFile file) {
        return toAjax(storageService.importCadZip(file));
    }


    @GetMapping("zip/{storageIds}")
    public void exportZipFiles(HttpServletRequest request, HttpServletResponse response,@PathVariable List<Long> storageIds) throws UnsupportedEncodingException {
        List<Storage> storages = storageService.listByIds(storageIds);
        List<String> urls = storages.stream().map(Storage::getUrl).collect(Collectors.toList());
        if (urls.size() > 0) {

            storageService.zip(response, urls);
        }

    }
    @GetMapping("zip4inspection/{projectIds}")
    public void exportZipFiles4Inspection(HttpServletRequest request, HttpServletResponse response,@PathVariable List<Long> projectIds) throws UnsupportedEncodingException {
        storageService.zipByProjectIds(response,projectIds);
    }


    @GetMapping("zipWithFileName")
    public void exportZip(HttpServletRequest request, HttpServletResponse response, @RequestParam("ids") List<Long> ids,String fileName) throws UnsupportedEncodingException {
        List<Storage> storages = storageService.listByIds(ids);
        List<String> urls = storages.stream().map(Storage::getUrl).collect(Collectors.toList());
        if (urls.size() > 0) {

            storageService.zip(response, urls,fileName);
        }

    }
}
